import sys
import os
import time
import threading
import base64
import json
from datetime import datetime
import io
from PIL import Image
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTabWidget, QWidget, 
                           QVBoxLayout, QHBoxLayout, QLabel, QPushButton, 
                           QFileDialog, QLineEdit, QTextEdit, QComboBox,
                           QProgressBar, QGroupBox, QRadioButton, QTableWidget,
                           QTableWidgetItem, QHeaderView, QSpinBox, QCheckBox,
                           QMessageBox, QSplitter, QFrame, QInputDialog)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer, QSize
from PyQt5.QtGui import QIcon, QPixmap, QFont

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import numpy as np

# 导入项目其他模块
from src.crypto_engine import CryptoEngine
from src.key_manager import KeyManager
from src.image_crypto import ImageCrypto
from src.security_tester import SecurityTester
from src.performance_analyzer import PerformanceAnalyzer

class EncryptionThread(QThread):
    """加密线程，避免GUI卡顿"""
    progress_update = pyqtSignal(int)
    finished = pyqtSignal(dict)
    error = pyqtSignal(str)
    
    def __init__(self, func, args, kwargs):
        super().__init__()
        self.func = func
        self.args = args
        self.kwargs = kwargs
    
    def run(self):
        try:
            # 模拟进度更新
            for i in range(0, 101, 5):
                self.progress_update.emit(i)
                time.sleep(0.05)
            
            # 执行加密/解密操作
            result = self.func(*self.args, **self.kwargs)
            self.finished.emit(result if isinstance(result, dict) else {'result': result})
        except Exception as e:
            self.error.emit(str(e))

class MatplotlibCanvas(FigureCanvas):
    """Matplotlib画布用于嵌入Qt界面"""
    def __init__(self, width=5, height=4, dpi=100):
        self.fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = self.fig.add_subplot(111)
        super().__init__(self.fig)
        self.fig.tight_layout()

class MainWindow(QMainWindow):
    """主窗口"""
    def __init__(self):
        super().__init__()
        
        # 初始化加密组件
        self.crypto_engine = CryptoEngine()
        self.key_manager = KeyManager()
        self.image_crypto = ImageCrypto()
        self.security_tester = SecurityTester()
        self.performance_analyzer = PerformanceAnalyzer()
        
        # 当前使用的密钥
        self.current_key = None
        self.current_key_id = None
        
        # 设置窗口
        self.setWindowTitle("数据加密系统")
        self.setGeometry(100, 100, 1200, 800)
        
        # 创建选项卡
        self.setup_ui()
    
    def setup_ui(self):
        """设置用户界面"""
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        
        # 主布局
        main_layout = QVBoxLayout(self.central_widget)
        
        # 创建选项卡
        self.tabs = QTabWidget()
        main_layout.addWidget(self.tabs)
        
        # 添加各个选项卡
        self.setup_text_encryption_tab()
        self.setup_file_encryption_tab()
        self.setup_image_encryption_tab()
        self.setup_key_management_tab()
        self.setup_security_testing_tab()
        self.setup_performance_tab()
        
        # 状态栏
        self.statusBar().showMessage("就绪")
    
    def setup_text_encryption_tab(self):
        """文本加密选项卡"""
        tab = QWidget()
        layout = QVBoxLayout(tab)
        
        # 密钥选择区域
        key_group = QGroupBox("密钥")
        key_layout = QHBoxLayout(key_group)
        
        self.text_key_select = QComboBox()
        self.text_key_select.setMinimumWidth(300)
        self.refresh_key_combobox(self.text_key_select)
        
        key_refresh_btn = QPushButton("刷新")
        key_refresh_btn.clicked.connect(lambda: self.refresh_key_combobox(self.text_key_select))
        
        key_generate_btn = QPushButton("生成新密钥")
        key_generate_btn.clicked.connect(self.generate_new_key)
        
        key_layout.addWidget(QLabel("选择密钥:"))
        key_layout.addWidget(self.text_key_select)
        key_layout.addWidget(key_refresh_btn)
        key_layout.addWidget(key_generate_btn)
        key_layout.addStretch()
        
        layout.addWidget(key_group)
        
        # 文本输入/输出区域
        text_splitter = QSplitter(Qt.Vertical)
        
        input_group = QGroupBox("输入文本")
        input_layout = QVBoxLayout(input_group)
        self.text_input = QTextEdit()
        input_layout.addWidget(self.text_input)
        
        output_group = QGroupBox("输出文本")
        output_layout = QVBoxLayout(output_group)
        self.text_output = QTextEdit()
        self.text_output.setReadOnly(True)
        output_layout.addWidget(self.text_output)
        
        text_splitter.addWidget(input_group)
        text_splitter.addWidget(output_group)
        layout.addWidget(text_splitter)
        
        # 操作按钮
        actions_layout = QHBoxLayout()
        
        self.encrypt_text_btn = QPushButton("加密")
        self.encrypt_text_btn.setIcon(QIcon.fromTheme("document-encrypt"))
        self.encrypt_text_btn.clicked.connect(self.encrypt_text)
        
        self.decrypt_text_btn = QPushButton("解密")
        self.decrypt_text_btn.setIcon(QIcon.fromTheme("document-decrypt"))
        self.decrypt_text_btn.clicked.connect(self.decrypt_text)
        
        clear_btn = QPushButton("清除")
        clear_btn.setIcon(QIcon.fromTheme("edit-clear"))
        clear_btn.clicked.connect(self.clear_text)
        
        self.text_progress = QProgressBar()
        self.text_progress.setRange(0, 100)
        self.text_progress.setValue(0)
        
        actions_layout.addWidget(self.encrypt_text_btn)
        actions_layout.addWidget(self.decrypt_text_btn)
        actions_layout.addWidget(clear_btn)
        actions_layout.addWidget(self.text_progress)
        
        layout.addLayout(actions_layout)
        
        self.tabs.addTab(tab, "文本加密")
    
    def setup_file_encryption_tab(self):
        """文件加密选项卡"""
        tab = QWidget()
        layout = QVBoxLayout(tab)
        
        # 密钥选择区域
        key_group = QGroupBox("密钥")
        key_layout = QHBoxLayout(key_group)
        
        self.file_key_select = QComboBox()
        self.file_key_select.setMinimumWidth(300)
        self.refresh_key_combobox(self.file_key_select)
        
        key_refresh_btn = QPushButton("刷新")
        key_refresh_btn.clicked.connect(lambda: self.refresh_key_combobox(self.file_key_select))
        
        key_layout.addWidget(QLabel("选择密钥:"))
        key_layout.addWidget(self.file_key_select)
        key_layout.addWidget(key_refresh_btn)
        key_layout.addStretch()
        
        layout.addWidget(key_group)
        
        # 文件选择区域
        file_group = QGroupBox("文件")
        file_layout = QVBoxLayout(file_group)
        
        input_file_layout = QHBoxLayout()
        self.file_input_path = QLineEdit()
        self.file_input_path.setReadOnly(True)
        input_file_btn = QPushButton("浏览...")
        input_file_btn.clicked.connect(self.browse_input_file)
        
        input_file_layout.addWidget(QLabel("输入文件:"))
        input_file_layout.addWidget(self.file_input_path)
        input_file_layout.addWidget(input_file_btn)
        
        output_file_layout = QHBoxLayout()
        self.file_output_path = QLineEdit()
        self.file_output_path.setReadOnly(True)
        output_file_btn = QPushButton("浏览...")
        output_file_btn.clicked.connect(self.browse_output_file)
        
        output_file_layout.addWidget(QLabel("输出文件:"))
        output_file_layout.addWidget(self.file_output_path)
        output_file_layout.addWidget(output_file_btn)
        
        file_layout.addLayout(input_file_layout)
        file_layout.addLayout(output_file_layout)
        
        layout.addWidget(file_group)
        
        # 操作按钮
        actions_layout = QHBoxLayout()
        
        self.encrypt_file_btn = QPushButton("加密文件")
        self.encrypt_file_btn.clicked.connect(self.encrypt_file)
        
        self.decrypt_file_btn = QPushButton("解密文件")
        self.decrypt_file_btn.clicked.connect(self.decrypt_file)
        
        self.file_progress = QProgressBar()
        self.file_progress.setRange(0, 100)
        self.file_progress.setValue(0)
        
        actions_layout.addWidget(self.encrypt_file_btn)
        actions_layout.addWidget(self.decrypt_file_btn)
        actions_layout.addWidget(self.file_progress)
        
        layout.addLayout(actions_layout)
        
        # 结果显示区域
        result_group = QGroupBox("处理结果")
        result_layout = QVBoxLayout(result_group)
        
        self.file_result_text = QTextEdit()
        self.file_result_text.setReadOnly(True)
        
        result_layout.addWidget(self.file_result_text)
        
        layout.addWidget(result_group)
        
        self.tabs.addTab(tab, "文件加密")
    
    def setup_image_encryption_tab(self):
        """图像加密选项卡"""
        tab = QWidget()
        layout = QVBoxLayout(tab)
        
        # 密钥选择区域
        key_group = QGroupBox("密钥")
        key_layout = QHBoxLayout(key_group)
        
        self.image_key_select = QComboBox()
        self.image_key_select.setMinimumWidth(300)
        self.refresh_key_combobox(self.image_key_select)
        
        key_refresh_btn = QPushButton("刷新")
        key_refresh_btn.clicked.connect(lambda: self.refresh_key_combobox(self.image_key_select))
        
        key_layout.addWidget(QLabel("选择密钥:"))
        key_layout.addWidget(self.image_key_select)
        key_layout.addWidget(key_refresh_btn)
        key_layout.addStretch()
        
        layout.addWidget(key_group)
        
        # 图像设置区域
        image_settings_group = QGroupBox("图像设置")
        image_settings_layout = QVBoxLayout(image_settings_group)
        
        input_image_layout = QHBoxLayout()
        self.image_input_path = QLineEdit()
        self.image_input_path.setReadOnly(True)
        input_image_btn = QPushButton("浏览...")
        input_image_btn.clicked.connect(self.browse_input_image)
        
        input_image_layout.addWidget(QLabel("输入图像:"))
        input_image_layout.addWidget(self.image_input_path)
        input_image_layout.addWidget(input_image_btn)
        
        output_image_layout = QHBoxLayout()
        self.image_output_path = QLineEdit()
        self.image_output_path.setReadOnly(True)
        output_image_btn = QPushButton("浏览...")
        output_image_btn.clicked.connect(self.browse_output_image)
        
        output_image_layout.addWidget(QLabel("输出图像:"))
        output_image_layout.addWidget(self.image_output_path)
        output_image_layout.addWidget(output_image_btn)
        
        algorithm_layout = QHBoxLayout()
        algorithm_layout.addWidget(QLabel("加密算法:"))
        
        self.image_algorithm = QComboBox()
        self.image_algorithm.addItem("AES-256-CBC", "aes")
        self.image_algorithm.addItem("混沌加密", "chaotic")
        
        algorithm_layout.addWidget(self.image_algorithm)
        algorithm_layout.addStretch()
        
        image_settings_layout.addLayout(input_image_layout)
        image_settings_layout.addLayout(output_image_layout)
        image_settings_layout.addLayout(algorithm_layout)
        
        layout.addWidget(image_settings_group)
        
        # 预览区域
        preview_layout = QHBoxLayout()
        
        original_group = QGroupBox("原始图像")
        original_layout = QVBoxLayout(original_group)
        self.original_image_label = QLabel()
        self.original_image_label.setAlignment(Qt.AlignCenter)
        self.original_image_label.setMinimumSize(300, 300)
        self.original_image_label.setScaledContents(True)
        original_layout.addWidget(self.original_image_label)
        
        encrypted_group = QGroupBox("加密/解密结果")
        encrypted_layout = QVBoxLayout(encrypted_group)
        self.encrypted_image_label = QLabel()
        self.encrypted_image_label.setAlignment(Qt.AlignCenter)
        self.encrypted_image_label.setMinimumSize(300, 300)
        self.encrypted_image_label.setScaledContents(True)
        encrypted_layout.addWidget(self.encrypted_image_label)
        
        preview_layout.addWidget(original_group)
        preview_layout.addWidget(encrypted_group)
        
        layout.addLayout(preview_layout)
        
        # 操作按钮
        actions_layout = QHBoxLayout()
        
        self.encrypt_image_btn = QPushButton("加密图像")
        self.encrypt_image_btn.clicked.connect(self.encrypt_image)
        
        self.decrypt_image_btn = QPushButton("解密图像")
        self.decrypt_image_btn.clicked.connect(self.decrypt_image)
        
        self.image_progress = QProgressBar()
        self.image_progress.setRange(0, 100)
        self.image_progress.setValue(0)
        
        actions_layout.addWidget(self.encrypt_image_btn)
        actions_layout.addWidget(self.decrypt_image_btn)
        actions_layout.addWidget(self.image_progress)
        
        layout.addLayout(actions_layout)
        
        # 性能信息
        perf_group = QGroupBox("性能信息")
        perf_layout = QVBoxLayout(perf_group)
        
        self.image_result_text = QTextEdit()
        self.image_result_text.setReadOnly(True)
        self.image_result_text.setMaximumHeight(100)
        
        perf_layout.addWidget(self.image_result_text)
        
        layout.addWidget(perf_group)
        
        self.tabs.addTab(tab, "图像加密")
    
    def setup_key_management_tab(self):
        """密钥管理选项卡"""
        tab = QWidget()
        layout = QVBoxLayout(tab)
        
        # 密钥列表区域
        keys_group = QGroupBox("密钥列表")
        keys_layout = QVBoxLayout(keys_group)
        
        self.keys_table = QTableWidget()
        self.keys_table.setColumnCount(5)
        self.keys_table.setHorizontalHeaderLabels(["密钥ID", "名称", "类型", "创建时间", "状态"])
        self.keys_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.keys_table.setSelectionMode(QTableWidget.SingleSelection)
        self.keys_table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.keys_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.keys_table.cellClicked.connect(self.select_key)
        
        refresh_keys_btn = QPushButton("刷新列表")
        refresh_keys_btn.clicked.connect(self.refresh_key_list)
        
        keys_layout.addWidget(self.keys_table)
        keys_layout.addWidget(refresh_keys_btn)
        
        layout.addWidget(keys_group)
        
        # 密钥操作区域
        actions_group = QGroupBox("密钥操作")
        actions_layout = QVBoxLayout(actions_group)
        
        # 新密钥创建
        new_key_layout = QHBoxLayout()
        
        self.new_key_name = QLineEdit()
        self.new_key_name.setPlaceholderText("输入新密钥名称")
        
        self.new_key_type = QComboBox()
        self.new_key_type.addItem("随机生成", "random")
        self.new_key_type.addItem("从密码派生", "derived")
        
        self.new_key_password = QLineEdit()
        self.new_key_password.setPlaceholderText("密码（仅派生模式需要）")
        self.new_key_password.setEchoMode(QLineEdit.Password)
        
        add_key_btn = QPushButton("添加密钥")
        add_key_btn.clicked.connect(self.add_key)
        
        new_key_layout.addWidget(QLabel("名称:"))
        new_key_layout.addWidget(self.new_key_name)
        new_key_layout.addWidget(QLabel("类型:"))
        new_key_layout.addWidget(self.new_key_type)
        new_key_layout.addWidget(self.new_key_password)
        new_key_layout.addWidget(add_key_btn)
        
        # 密钥管理操作
        key_actions_layout = QHBoxLayout()
        
        rotate_key_btn = QPushButton("轮换密钥")
        rotate_key_btn.clicked.connect(self.rotate_key)
        
        revoke_key_btn = QPushButton("撤销密钥")
        revoke_key_btn.clicked.connect(self.revoke_key)
        
        delete_key_btn = QPushButton("删除密钥")
        delete_key_btn.clicked.connect(self.delete_key)
        
        export_key_btn = QPushButton("导出密钥")
        export_key_btn.clicked.connect(self.export_key)
        
        key_actions_layout.addWidget(rotate_key_btn)
        key_actions_layout.addWidget(revoke_key_btn)
        key_actions_layout.addWidget(delete_key_btn)
        key_actions_layout.addWidget(export_key_btn)
        
        actions_layout.addLayout(new_key_layout)
        actions_layout.addLayout(key_actions_layout)
        
        layout.addWidget(actions_group)
        
        # 密钥详情区域
        details_group = QGroupBox("密钥详情")
        details_layout = QVBoxLayout(details_group)
        
        self.key_details = QTextEdit()
        self.key_details.setReadOnly(True)
        
        details_layout.addWidget(self.key_details)
        
        layout.addWidget(details_group)
        
        self.tabs.addTab(tab, "密钥管理")
    
    def setup_security_testing_tab(self):
        """安全性测试选项卡"""
        tab = QWidget()
        layout = QVBoxLayout(tab)
        
        # 密钥选择区域
        key_group = QGroupBox("密钥")
        key_layout = QHBoxLayout(key_group)
        
        self.security_key_select = QComboBox()
        self.security_key_select.setMinimumWidth(300)
        self.refresh_key_combobox(self.security_key_select)
        
        key_refresh_btn = QPushButton("刷新")
        key_refresh_btn.clicked.connect(lambda: self.refresh_key_combobox(self.security_key_select))
        
        key_layout.addWidget(QLabel("选择密钥:"))
        key_layout.addWidget(self.security_key_select)
        key_layout.addWidget(key_refresh_btn)
        key_layout.addStretch()
        
        layout.addWidget(key_group)
        
        # 测试选项区域
        test_group = QGroupBox("测试选项")
        test_layout = QVBoxLayout(test_group)
        
        tests_layout = QHBoxLayout()
        
        self.test_nist = QCheckBox("NIST随机性测试")
        self.test_nist.setChecked(True)
        
        self.test_plaintext = QCheckBox("已知明文攻击模拟")
        self.test_plaintext.setChecked(True)
        
        self.test_ciphertext = QCheckBox("选择密文攻击模拟")
        self.test_ciphertext.setChecked(True)
        
        self.test_forward = QCheckBox("前向安全性分析")
        self.test_forward.setChecked(True)
        
        tests_layout.addWidget(self.test_nist)
        tests_layout.addWidget(self.test_plaintext)
        tests_layout.addWidget(self.test_ciphertext)
        tests_layout.addWidget(self.test_forward)
        
        sample_layout = QHBoxLayout()
        sample_layout.addWidget(QLabel("样本数量:"))
        
        self.test_samples = QSpinBox()
        self.test_samples.setRange(10, 1000)
        self.test_samples.setValue(100)
        self.test_samples.setSingleStep(10)
        
        sample_layout.addWidget(self.test_samples)
        sample_layout.addStretch()
        
        test_btn = QPushButton("开始测试")
        test_btn.clicked.connect(self.security_test)
        
        test_layout.addLayout(tests_layout)
        test_layout.addLayout(sample_layout)
        test_layout.addWidget(test_btn)
        
        layout.addWidget(test_group)
        
        # 结果显示区域
        results_group = QGroupBox("测试结果")
        results_layout = QVBoxLayout(results_group)
        
        self.security_results = QTextEdit()
        self.security_results.setReadOnly(True)
        
        results_layout.addWidget(self.security_results)
        
        layout.addWidget(results_group)
        
        # 可视化区域
        viz_group = QGroupBox("可视化结果")
        viz_layout = QVBoxLayout(viz_group)
        
        self.security_viz_canvas = MatplotlibCanvas(width=5, height=4, dpi=100)
        viz_layout.addWidget(self.security_viz_canvas)
        
        layout.addWidget(viz_group)
        
        self.tabs.addTab(tab, "安全性测试")
    
    def setup_performance_tab(self):
        """性能分析选项卡"""
        tab = QWidget()
        layout = QVBoxLayout(tab)
        
        # 密钥选择区域
        key_group = QGroupBox("密钥")
        key_layout = QHBoxLayout(key_group)
        
        self.perf_key_select = QComboBox()
        self.perf_key_select.setMinimumWidth(300)
        self.refresh_key_combobox(self.perf_key_select)
        
        key_refresh_btn = QPushButton("刷新")
        key_refresh_btn.clicked.connect(lambda: self.refresh_key_combobox(self.perf_key_select))
        
        key_layout.addWidget(QLabel("选择密钥:"))
        key_layout.addWidget(self.perf_key_select)
        key_layout.addWidget(key_refresh_btn)
        key_layout.addStretch()
        
        layout.addWidget(key_group)
        
        # 测试选项区域
        test_group = QGroupBox("测试选项")
        test_layout = QVBoxLayout(test_group)
        
        tests_layout = QHBoxLayout()
        
        self.perf_throughput = QCheckBox("吞吐量测试")
        self.perf_throughput.setChecked(True)
        
        self.perf_key_gen = QCheckBox("密钥生成性能")
        self.perf_key_gen.setChecked(True)
        
        self.perf_memory = QCheckBox("内存使用分析")
        self.perf_memory.setChecked(True)
        
        self.perf_enc_dec = QCheckBox("加密/解密比较")
        self.perf_enc_dec.setChecked(True)
        
        tests_layout.addWidget(self.perf_throughput)
        tests_layout.addWidget(self.perf_key_gen)
        tests_layout.addWidget(self.perf_memory)
        tests_layout.addWidget(self.perf_enc_dec)
        
        # 添加测试输入文本区域
        test_input_layout = QVBoxLayout()
        test_input_layout.addWidget(QLabel("测试输入文本:"))
        
        self.perf_test_input = QTextEdit()
        self.perf_test_input.setPlaceholderText("请在此处输入用于性能测试的文本...")
        self.perf_test_input.setMaximumHeight(100)
        test_input_layout.addWidget(self.perf_test_input)
        
        iterations_layout = QHBoxLayout()
        iterations_layout.addWidget(QLabel("测试迭代次数:"))
        
        self.perf_iterations = QSpinBox()
        self.perf_iterations.setRange(1, 10)
        self.perf_iterations.setValue(3)
        
        iterations_layout.addWidget(self.perf_iterations)
        iterations_layout.addStretch()
        
        report_layout = QHBoxLayout()
        report_layout.addWidget(QLabel("生成HTML报告:"))
        
        self.perf_report = QCheckBox()
        self.perf_report.setChecked(True)
        
        report_layout.addWidget(self.perf_report)
        report_layout.addStretch()
        
        test_btn = QPushButton("开始性能测试")
        test_btn.clicked.connect(self.performance_test)
        
        test_layout.addLayout(tests_layout)
        test_layout.addLayout(test_input_layout)
        test_layout.addLayout(iterations_layout)
        test_layout.addLayout(report_layout)
        test_layout.addWidget(test_btn)
        
        layout.addWidget(test_group)
        
        # 结果显示区域
        results_splitter = QSplitter(Qt.Vertical)
        
        results_group = QGroupBox("测试结果")
        results_layout = QVBoxLayout(results_group)
        
        self.perf_results = QTextEdit()
        self.perf_results.setReadOnly(True)
        
        results_layout.addWidget(self.perf_results)
        
        # 可视化区域
        viz_group = QGroupBox("性能图表")
        viz_layout = QVBoxLayout(viz_group)
        
        self.perf_viz_canvas = MatplotlibCanvas(width=8, height=4, dpi=100)
        viz_layout.addWidget(self.perf_viz_canvas)
        
        results_splitter.addWidget(results_group)
        results_splitter.addWidget(viz_group)
        
        layout.addWidget(results_splitter)
        
        self.tabs.addTab(tab, "性能分析")
    
    def refresh_key_combobox(self, combobox):
        """刷新密钥下拉选择框"""
        combobox.clear()
        keys = self.key_manager.list_keys()
        for key in keys:
            status = "有效" if key['is_active'] else "无效"
            combobox.addItem(f"{key['name']} ({key['type']}, {status})", key['id'])
    
    def refresh_key_list(self):
        """刷新密钥列表"""
        self.keys_table.setRowCount(0)
        
        # 获取所有密钥（包括已撤销和过期的）
        keys = self.key_manager.list_keys(include_revoked=True, include_expired=True)
        
        for i, key in enumerate(keys):
            self.keys_table.insertRow(i)
            self.keys_table.setItem(i, 0, QTableWidgetItem(key['id']))
            self.keys_table.setItem(i, 1, QTableWidgetItem(key['name']))
            self.keys_table.setItem(i, 2, QTableWidgetItem(key['type']))
            
            # 格式化日期时间显示
            created_at = key['created_at']
            created_at_str = created_at.strftime("%Y-%m-%d %H:%M") if created_at else "未知"
            self.keys_table.setItem(i, 3, QTableWidgetItem(created_at_str))
            
            # 设置状态
            status = "有效" if key['is_active'] else "无效"
            if key['revoked_at']:
                status = "已撤销"
            elif key['expires_at'] and key['expires_at'] < datetime.now():
                status = "已过期"
            self.keys_table.setItem(i, 4, QTableWidgetItem(status))
    
    def select_key(self, row, column):
        """选择密钥行"""
        key_id = self.keys_table.item(row, 0).text()
        
        # 设置当前选择的密钥ID
        self.current_key_id = key_id
        
        # 显示密钥详情
        try:
            conn = self.key_manager._get_connection()
            cursor = conn.cursor()
            cursor.execute("""
            SELECT k.*, 
                   (SELECT COUNT(*) FROM key_usage ku WHERE ku.key_id = k.id) as usage_count,
                   (SELECT MAX(timestamp) FROM key_usage ku WHERE ku.key_id = k.id) as last_used
            FROM keys k
            WHERE k.id = ?
            """, (key_id,))
            
            result = cursor.fetchone()
            if result:
                # 格式化日期
                created_at = datetime.datetime.fromisoformat(result['created_at']) if result['created_at'] else None
                expires_at = datetime.datetime.fromisoformat(result['expires_at']) if result['expires_at'] else None
                revoked_at = datetime.datetime.fromisoformat(result['revoked_at']) if result['revoked_at'] else None
                last_used = datetime.datetime.fromisoformat(result['last_used']) if result['last_used'] else None
                
                details = f"密钥ID: {result['id']}\n"
                details += f"名称: {result['key_name']}\n"
                details += f"类型: {result['key_type']}\n"
                details += f"创建时间: {created_at}\n"
                
                if expires_at:
                    details += f"过期时间: {expires_at}\n"
                else:
                    details += "过期时间: 永不过期\n"
                
                if revoked_at:
                    details += f"撤销时间: {revoked_at}\n"
                
                details += f"使用次数: {result['usage_count']}\n"
                
                if last_used:
                    details += f"最后使用时间: {last_used}\n"
                
                if result['metadata']:
                    details += f"\n元数据: {result['metadata']}\n"
                
                self.key_details.setText(details)
            else:
                self.key_details.setText(f"没有找到ID为 {key_id} 的密钥")
        except Exception as e:
            self.key_details.setText(f"获取密钥详情时出错: {str(e)}")
    
    def add_key(self):
        """添加新密钥"""
        name = self.new_key_name.text()
        key_type = self.new_key_type.currentData()
        password = self.new_key_password.text()
        
        if not name:
            QMessageBox.warning(self, "警告", "请输入密钥名称")
            return
        
        try:
            if key_type == "derived":
                if not password:
                    QMessageBox.warning(self, "警告", "派生密钥需要输入密码")
                    return
                
                key_id, gen_time = self.key_manager.create_derived_key(name, password)
                method = "派生"
            else:
                key_id, gen_time = self.key_manager.create_key(name)
                method = "随机生成"
            
            QMessageBox.information(self, "密钥创建成功", 
                                   f"密钥已{method}成功！\nID: {key_id}\n生成时间: {gen_time:.2f}ms")
            
            # 清空输入
            self.new_key_name.clear()
            self.new_key_password.clear()
            
            # 刷新密钥列表
            self.refresh_key_list()
            
            # 刷新所有密钥下拉框
            self.refresh_key_combobox(self.text_key_select)
            self.refresh_key_combobox(self.file_key_select)
            self.refresh_key_combobox(self.image_key_select)
            self.refresh_key_combobox(self.security_key_select)
            self.refresh_key_combobox(self.perf_key_select)
            
        except Exception as e:
            QMessageBox.critical(self, "错误", f"创建密钥失败: {str(e)}")
    
    def rotate_key(self):
        """轮换密钥"""
        if not self.current_key_id:
            QMessageBox.warning(self, "警告", "请先选择一个密钥")
            return
        
        reply = QMessageBox.question(self, "确认轮换", 
                                    f"确定要轮换ID为 {self.current_key_id} 的密钥吗？\n这将创建一个新密钥并撤销当前密钥。",
                                    QMessageBox.Yes | QMessageBox.No)
        
        if reply == QMessageBox.Yes:
            try:
                new_key_id, rotation_time = self.key_manager.rotate_key(self.current_key_id)
                
                QMessageBox.information(self, "密钥轮换成功", 
                                       f"密钥已轮换成功！\n新密钥ID: {new_key_id}\n轮换时间: {rotation_time:.2f}ms")
                
                # 刷新密钥列表
                self.refresh_key_list()
                
                # 刷新所有密钥下拉框
                self.refresh_key_combobox(self.text_key_select)
                self.refresh_key_combobox(self.file_key_select)
                self.refresh_key_combobox(self.image_key_select)
                self.refresh_key_combobox(self.security_key_select)
                self.refresh_key_combobox(self.perf_key_select)
                
            except Exception as e:
                QMessageBox.critical(self, "错误", f"轮换密钥失败: {str(e)}")
    
    def revoke_key(self):
        """撤销密钥"""
        if not self.current_key_id:
            QMessageBox.warning(self, "警告", "请先选择一个密钥")
            return
        
        reply = QMessageBox.question(self, "确认撤销", 
                                    f"确定要撤销ID为 {self.current_key_id} 的密钥吗？\n撤销后该密钥将无法用于加密/解密操作。",
                                    QMessageBox.Yes | QMessageBox.No)
        
        if reply == QMessageBox.Yes:
            try:
                success = self.key_manager.revoke_key(self.current_key_id)
                
                if success:
                    QMessageBox.information(self, "密钥撤销成功", "密钥已成功撤销")
                else:
                    QMessageBox.warning(self, "操作失败", "密钥撤销失败")
                
                # 刷新密钥列表
                self.refresh_key_list()
                
                # 刷新所有密钥下拉框
                self.refresh_key_combobox(self.text_key_select)
                self.refresh_key_combobox(self.file_key_select)
                self.refresh_key_combobox(self.image_key_select)
                self.refresh_key_combobox(self.security_key_select)
                self.refresh_key_combobox(self.perf_key_select)
                
            except Exception as e:
                QMessageBox.critical(self, "错误", f"撤销密钥失败: {str(e)}")
    
    def delete_key(self):
        """删除密钥（仅从UI删除，实际数据库记录保留）"""
        if not self.current_key_id:
            QMessageBox.warning(self, "警告", "请先选择一个密钥")
            return
        
        reply = QMessageBox.question(self, "确认删除", 
                                    f"确定要从列表中删除ID为 {self.current_key_id} 的密钥吗？\n该操作不会从数据库中删除密钥记录，但会从界面中隐藏。",
                                    QMessageBox.Yes | QMessageBox.No)
        
        if reply == QMessageBox.Yes:
            try:
                # 这里我们只是从UI中隐藏密钥，实际上不删除记录
                # 实现上，我们可以直接刷新列表，忽略被标记为"删除"的密钥
                
                # 创建一个标记删除的元数据
                conn = self.key_manager._get_connection()
                cursor = conn.cursor()
                cursor.execute("""
                SELECT metadata FROM keys WHERE id = ?
                """, (self.current_key_id,))
                
                result = cursor.fetchone()
                metadata_str = result['metadata'] if result and result['metadata'] else '{}'
                metadata_dict = json.loads(metadata_str)
                
                # 标记为已删除
                metadata_dict['deleted'] = True
                metadata_dict['deleted_at'] = datetime.now().isoformat()
                
                cursor.execute("""
                UPDATE keys SET metadata = ? WHERE id = ?
                """, (json.dumps(metadata_dict), self.current_key_id))
                
                conn.commit()
                
                QMessageBox.information(self, "删除成功", f"密钥 {self.current_key_id} 已从列表中删除")
                
                # 刷新密钥列表
                self.refresh_key_list()
                
                # 刷新所有密钥下拉框
                self.refresh_key_combobox(self.text_key_select)
                self.refresh_key_combobox(self.file_key_select)
                self.refresh_key_combobox(self.image_key_select)
                self.refresh_key_combobox(self.security_key_select)
                self.refresh_key_combobox(self.perf_key_select)
                
            except Exception as e:
                QMessageBox.critical(self, "错误", f"删除密钥失败: {str(e)}")
    
    def export_key(self):
        """导出密钥"""
        if not self.current_key_id:
            QMessageBox.warning(self, "警告", "请先选择一个密钥")
            return
        
        # 获取密钥数据
        try:
            conn = self.key_manager._get_connection()
            cursor = conn.cursor()
            cursor.execute("""
            SELECT key_name, key_type, key_data, salt FROM keys WHERE id = ?
            """, (self.current_key_id,))
            
            result = cursor.fetchone()
            if not result:
                QMessageBox.warning(self, "错误", f"找不到ID为 {self.current_key_id} 的密钥")
                return
            
            key_name = result['key_name']
            key_type = result['key_type']
            key_data = result['key_data']  # Base64编码的密钥数据
            salt = result['salt']        # Base64编码的盐值（如果有）
            
            # 创建导出信息
            export_data = {
                "id": self.current_key_id,
                "name": key_name,
                "type": key_type,
                "key": key_data,
                "salt": salt,
                "exported_at": datetime.now().isoformat(),
                "version": "1.0"
            }
            
            # 导出为JSON文件
            filename, _ = QFileDialog.getSaveFileName(
                self, "导出密钥", f"{key_name}_{self.current_key_id[:8]}.key", "密钥文件 (*.key)")
            
            if filename:
                with open(filename, 'w') as f:
                    json.dump(export_data, f, indent=2)
                
                QMessageBox.information(self, "导出成功", f"密钥已导出到: {filename}")
        
        except Exception as e:
            QMessageBox.critical(self, "错误", f"导出密钥失败: {str(e)}")
    
    def security_test(self):
        """执行安全性测试"""
        key_id = self.security_key_select.currentData()
        if not key_id:
            QMessageBox.warning(self, "警告", "请选择密钥")
            return
        
        # 获取选项
        run_nist = self.test_nist.isChecked()
        run_plaintext = self.test_plaintext.isChecked()
        run_ciphertext = self.test_ciphertext.isChecked()
        run_forward = self.test_forward.isChecked()
        
        if not (run_nist or run_plaintext or run_ciphertext or run_forward):
            QMessageBox.warning(self, "警告", "请选择至少一项测试")
            return
        
        samples = self.test_samples.value()
        
        try:
            # 获取密钥
            key = self.key_manager.get_key(key_id=key_id)
            if not key:
                raise ValueError("获取密钥失败")
            
            self.security_results.clear()
            self.security_results.append("正在执行安全性测试...\n")
            
            results = {}
            
            # NIST随机性测试
            if run_nist:
                self.security_results.append("执行NIST随机性测试...")
                
                # 生成一些随机明文并加密
                test_data = os.urandom(10240)  # 10KB随机数据
                encrypted_data, iv = self.crypto_engine.encrypt(test_data, key)
                
                # 执行随机性测试
                nist_results = self.security_tester.run_nist_randomness_tests(encrypted_data)
                results['nist'] = nist_results
                
                # 显示结果摘要
                summary = nist_results['summary']
                self.security_results.append(f"NIST测试结果: {summary['passed_tests']}/{summary['total_tests']} 通过 ({summary['pass_rate']*100:.1f}%)")
                self.security_results.append(f"整体评估: {'通过' if summary['overall_pass'] else '未通过'}\n")
                
                # 显示详细测试结果
                for test_name, test_result in nist_results.items():
                    if test_name != 'summary':
                        self.security_results.append(f"- {test_result['name']}: {'通过' if test_result.get('pass', False) else '未通过'}")
                
                self.security_results.append("")
            
            # 已知明文攻击模拟
            if run_plaintext:
                self.security_results.append("执行已知明文攻击模拟...")
                
                # 定义加密函数
                encrypt_func = lambda plaintext, key: self.crypto_engine.encrypt(plaintext, key)[0]
                
                # 执行攻击模拟
                plaintext_results = self.security_tester.simulate_known_plaintext_attack(encrypt_func, key, samples)
                results['plaintext'] = plaintext_results
                
                # 显示结果
                self.security_results.append(f"已知明文攻击模拟结果: {'通过' if plaintext_results['pass'] else '未通过'}")
                self.security_results.append(f"样本数量: {plaintext_results['samples']}")
                self.security_results.append(f"明文-密文平均相关性: {plaintext_results['avg_correlation']:.6f}")
                self.security_results.append(f"明文熵: {plaintext_results['plaintext_entropy']:.4f}")
                self.security_results.append(f"密文熵: {plaintext_results['ciphertext_entropy']:.4f}\n")
            
            # 选择密文攻击模拟
            if run_ciphertext:
                self.security_results.append("执行选择密文攻击模拟...")
                
                # 定义解密函数
                def decrypt_func(ciphertext, key):
                    try:
                        # 假设前16字节是IV
                        if len(ciphertext) < 32:  # 确保有足够的数据
                            return b''
                        
                        iv = ciphertext[:16]
                        encrypted_data = ciphertext[16:]
                        return self.crypto_engine.decrypt(encrypted_data, key, iv)
                    except:
                        return b''
                
                # 执行攻击模拟
                ciphertext_results = self.security_tester.simulate_chosen_ciphertext_attack(decrypt_func, key, samples)
                results['ciphertext'] = ciphertext_results
                
                # 显示结果
                self.security_results.append(f"选择密文攻击模拟结果: {'通过' if ciphertext_results['pass'] else '未通过'}")
                self.security_results.append(f"样本数量: {ciphertext_results['samples']}")
                self.security_results.append(f"有效样本: {ciphertext_results['valid_samples']} ({ciphertext_results.get('valid_ratio', 0)*100:.1f}%)")
                
                if ciphertext_results.get('avg_correlation') is not None:
                    self.security_results.append(f"密文-解密文本平均相关性: {ciphertext_results['avg_correlation']:.6f}")
                
                if ciphertext_results.get('message'):
                    self.security_results.append(f"附加信息: {ciphertext_results['message']}")
                
                self.security_results.append("")
            
            # 前向安全性分析
            if run_forward:
                self.security_results.append("执行前向安全性分析...")
                
                # 定义加密函数
                encrypt_func = lambda plaintext, key: self.crypto_engine.encrypt(plaintext, key)[0]
                
                # 定义密钥轮换函数
                def rotate_key_func(old_key):
                    # 简单实现: 生成新的随机密钥
                    return os.urandom(len(old_key))
                
                # 测试明文
                test_plaintext = b"This is a test message for forward security analysis."
                
                # 执行分析
                forward_results = self.security_tester.analyze_forward_security(encrypt_func, rotate_key_func, test_plaintext)
                results['forward'] = forward_results
                
                # 显示结果
                self.security_results.append(f"前向安全性分析结果: {'通过' if forward_results['pass'] else '未通过'}")
                self.security_results.append(f"密钥轮换次数: {forward_results['rotations']}")
                self.security_results.append(f"密文平均相似度: {forward_results['avg_similarity']:.6f}")
                self.security_results.append(f"理想相似度: {forward_results['expected_similarity']}")
                self.security_results.append("")
            
            # 整体安全性评估
            overall_pass = all(r.get('pass', False) for r in results.values())
            
            self.security_results.append("\n===== 整体安全性评估 =====")
            self.security_results.append(f"总体评估: {'通过' if overall_pass else '存在潜在风险'}")
            
            if not overall_pass:
                self.security_results.append("\n可能存在的安全风险:")
                if results.get('nist') and not results['nist']['summary']['overall_pass']:
                    self.security_results.append("- 密文随机性不足，可能暴露模式")
                if results.get('plaintext') and not results['plaintext']['pass']:
                    self.security_results.append("- 明文和密文间存在统计关联，易受已知明文攻击")
                if results.get('ciphertext') and not results['ciphertext']['pass']:
                    self.security_results.append("- 解密函数对错误输入的鲁棒性不足，易受选择密文攻击")
                if results.get('forward') and not results['forward']['pass']:
                    self.security_results.append("- 密钥轮换后，密文相似度异常，前向安全性不佳")
            
            # 绘制可视化图表
            if run_nist:
                try:
                    # 创建字节频率分布
                    self.security_viz_canvas.axes.clear()
                    byte_counts = [0] * 256
                    
                    # 计算字节频率
                    for b in encrypted_data:
                        byte_counts[b] += 1
                    
                    # 归一化频率
                    total_bytes = len(encrypted_data)
                    byte_freqs = [count / total_bytes for count in byte_counts]
                    
                    # 直接在画布上绘制柱状图
                    self.security_viz_canvas.axes.bar(range(256), byte_freqs, width=1.0)
                    self.security_viz_canvas.axes.set_title("加密数据字节分布")
                    self.security_viz_canvas.axes.set_xlabel("字节值")
                    self.security_viz_canvas.axes.set_ylabel("频率")
                    self.security_viz_canvas.draw()
                except Exception as viz_error:
                    self.security_results.append(f"\n可视化图表生成失败: {str(viz_error)}")
            
            elif run_plaintext:
                try:
                    # 创建熵比较图表(不依赖于visualize_entropy函数)
                    self.security_viz_canvas.axes.clear()
                    
                    # 使用测试结果中的熵值
                    plain_entropy = plaintext_results.get('plaintext_entropy', 0)
                    cipher_entropy = plaintext_results.get('ciphertext_entropy', 0)
                    
                    # 简单的柱状图
                    self.security_viz_canvas.axes.bar(['原始数据', '加密数据'], [plain_entropy, cipher_entropy], color=['blue', 'red'])
                    self.security_viz_canvas.axes.set_title("数据熵比较")
                    self.security_viz_canvas.axes.set_ylabel("熵 (bits)")
                    self.security_viz_canvas.draw()
                except Exception as viz_error:
                    self.security_results.append(f"\n可视化图表生成失败: {str(viz_error)}")
            
            self.statusBar().showMessage("安全性测试完成")
            
        except Exception as e:
            self.security_results.append(f"测试过程中出错: {str(e)}")
            import traceback
            self.security_results.append(traceback.format_exc())

    def encrypt_text(self):
        """加密文本"""
        text = self.text_input.toPlainText()
        if not text:
            QMessageBox.warning(self, "警告", "请输入要加密的文本")
            return
        
        key_id = self.text_key_select.currentData()
        if not key_id:
            QMessageBox.warning(self, "警告", "请选择密钥")
            return
        
        try:
            # 获取密钥
            key = self.key_manager.get_key(key_id=key_id)
            if not key:
                raise ValueError("获取密钥失败")
            
            # 创建并启动加密线程
            self.encryption_thread = EncryptionThread(
                func=lambda data, key: self.crypto_engine.encrypt(data, key),
                args=(text, key),
                kwargs={}
            )
            
            self.encryption_thread.progress_update.connect(self.text_progress.setValue)
            self.encryption_thread.finished.connect(self.handle_text_encryption_result)
            self.encryption_thread.error.connect(self.handle_encryption_error)
            
            self.encryption_thread.start()
            
            # 禁用按钮直到加密完成
            self.encrypt_text_btn.setEnabled(False)
            self.decrypt_text_btn.setEnabled(False)
            
        except Exception as e:
            QMessageBox.critical(self, "加密错误", str(e))
    
    def handle_text_encryption_result(self, result):
        """处理文本加密结果"""
        try:
            encrypted_data, iv = result['result']
            
            # 将二进制数据转换为Base64字符串
            b64_data = self.crypto_engine.base64_encode(encrypted_data)
            b64_iv = self.crypto_engine.base64_encode(iv)
            
            # 显示结果
            self.text_output.setText(f"IV: {b64_iv}\n\n加密结果:\n{b64_data}")
            
            # 恢复按钮状态
            self.encrypt_text_btn.setEnabled(True)
            self.decrypt_text_btn.setEnabled(True)
            
            self.statusBar().showMessage("加密完成")
            
        except Exception as e:
            QMessageBox.critical(self, "处理加密结果错误", str(e))
            self.encrypt_text_btn.setEnabled(True)
            self.decrypt_text_btn.setEnabled(True)
    
    def decrypt_text(self):
        """解密文本"""
        text = self.text_input.toPlainText()
        if not text:
            QMessageBox.warning(self, "警告", "请输入要解密的文本")
            return
        
        key_id = self.text_key_select.currentData()
        if not key_id:
            QMessageBox.warning(self, "警告", "请选择密钥")
            return
        
        try:
            # 尝试解析输入格式
            lines = text.strip().split('\n')
            if len(lines) < 2 or not lines[0].startswith("IV:"):
                raise ValueError("解密输入格式错误。需要IV和加密数据")
            
            iv_b64 = lines[0].replace("IV:", "").strip()
            encrypted_b64 = '\n'.join(lines[2:]).strip()
            
            # 解码Base64
            iv = self.crypto_engine.base64_decode(iv_b64)
            encrypted_data = self.crypto_engine.base64_decode(encrypted_b64)
            
            # 获取密钥
            key = self.key_manager.get_key(key_id=key_id)
            if not key:
                raise ValueError("获取密钥失败")
            
            # 创建并启动解密线程
            self.decryption_thread = EncryptionThread(
                func=lambda encrypted_data, key, iv: self.crypto_engine.decrypt(encrypted_data, key, iv),
                args=(encrypted_data, key, iv),
                kwargs={}
            )
            
            self.decryption_thread.progress_update.connect(self.text_progress.setValue)
            self.decryption_thread.finished.connect(self.handle_text_decryption_result)
            self.decryption_thread.error.connect(self.handle_encryption_error)
            
            self.decryption_thread.start()
            
            # 禁用按钮直到解密完成
            self.encrypt_text_btn.setEnabled(False)
            self.decrypt_text_btn.setEnabled(False)
            
        except Exception as e:
            QMessageBox.critical(self, "解密错误", str(e))
    
    def handle_text_decryption_result(self, result):
        """处理文本解密结果"""
        try:
            decrypted_data = result['result']
            
            # 将二进制数据转换为文本
            text = decrypted_data.decode('utf-8')
            
            # 显示结果
            self.text_output.setText(text)
            
            # 恢复按钮状态
            self.encrypt_text_btn.setEnabled(True)
            self.decrypt_text_btn.setEnabled(True)
            
            self.statusBar().showMessage("解密完成")
            
        except Exception as e:
            QMessageBox.critical(self, "处理解密结果错误", str(e))
            self.encrypt_text_btn.setEnabled(True)
            self.decrypt_text_btn.setEnabled(True)
    
    def handle_encryption_error(self, error_msg):
        """处理加密/解密错误"""
        QMessageBox.critical(self, "错误", error_msg)
        self.encrypt_text_btn.setEnabled(True)
        self.decrypt_text_btn.setEnabled(True)
        self.text_progress.setValue(0)
    
    def clear_text(self):
        """清除文本输入/输出框"""
        self.text_input.clear()
        self.text_output.clear()
        self.text_progress.setValue(0)
    
    def browse_input_file(self):
        """浏览输入文件"""
        fname, _ = QFileDialog.getOpenFileName(self, "选择输入文件", "", "所有文件 (*)")
        if fname:
            self.file_input_path.setText(fname)
            
            # 自动设置输出文件路径
            base, ext = os.path.splitext(fname)
            if self.encrypt_file_btn.isEnabled():  # 如果是加密模式
                self.file_output_path.setText(f"{base}_encrypted{ext}")
            else:  # 如果是解密模式
                self.file_output_path.setText(f"{base}_decrypted{ext}")
    
    def browse_output_file(self):
        """浏览输出文件"""
        fname, _ = QFileDialog.getSaveFileName(self, "选择输出文件", "", "所有文件 (*)")
        if fname:
            self.file_output_path.setText(fname)
    
    def encrypt_file(self):
        """加密文件"""
        input_path = self.file_input_path.text()
        output_path = self.file_output_path.text()
        
        if not input_path or not os.path.exists(input_path):
            QMessageBox.warning(self, "警告", "请选择有效的输入文件")
            return
            
        if not output_path:
            QMessageBox.warning(self, "警告", "请选择有效的输出文件")
            return
        
        key_id = self.file_key_select.currentData()
        if not key_id:
            QMessageBox.warning(self, "警告", "请选择密钥")
            return
        
        try:
            # 获取密钥
            key = self.key_manager.get_key(key_id=key_id)
            if not key:
                raise ValueError("获取密钥失败")
            
            # 创建并启动加密线程
            self.file_encryption_thread = EncryptionThread(
                func=lambda input_path, output_path, key: self.crypto_engine.encrypt_file(input_path, output_path, key),
                args=(input_path, output_path, key),
                kwargs={}
            )
            
            self.file_encryption_thread.progress_update.connect(self.file_progress.setValue)
            self.file_encryption_thread.finished.connect(self.handle_file_encryption_result)
            self.file_encryption_thread.error.connect(self.handle_file_operation_error)
            
            self.file_encryption_thread.start()
            
            # 禁用按钮直到加密完成
            self.encrypt_file_btn.setEnabled(False)
            self.decrypt_file_btn.setEnabled(False)
            
        except Exception as e:
            QMessageBox.critical(self, "文件加密错误", str(e))
    
    def handle_file_encryption_result(self, result):
        """处理文件加密结果"""
        try:
            # 修复这里，处理result可能是字典的情况
            if isinstance(result, dict) and 'result' in result:
                iv, encryption_time = result['result']
            else:
                iv, encryption_time = result
            
            # 显示结果
            file_size = os.path.getsize(self.file_input_path.text()) / (1024 * 1024)  # MB
            
            # 避免除零错误，确保加密时间至少为1毫秒
            encryption_time_sec = max(encryption_time / 1000, 0.001)  # 转换为秒并确保不为零
            throughput = file_size / encryption_time_sec
            
            self.file_result_text.setText(
                f"文件加密成功！\n"
                f"输出文件: {self.file_output_path.text()}\n"
                f"文件大小: {file_size:.2f} MB\n"
                f"加密时间: {encryption_time:.2f} ms\n"
                f"加密吞吐量: {throughput:.2f} MB/s"
            )
            
            # 恢复按钮状态
            self.encrypt_file_btn.setEnabled(True)
            self.decrypt_file_btn.setEnabled(True)
            
            self.statusBar().showMessage("文件加密完成")
            
        except Exception as e:
            print(f"处理文件加密结果错误: {str(e)}")
            QMessageBox.critical(self, "处理文件加密结果错误", str(e))
            self.encrypt_file_btn.setEnabled(True)
            self.decrypt_file_btn.setEnabled(True)
    
    def decrypt_file(self):
        """解密文件"""
        input_path = self.file_input_path.text()
        output_path = self.file_output_path.text()
        
        if not input_path or not os.path.exists(input_path):
            QMessageBox.warning(self, "警告", "请选择有效的输入文件")
            return
            
        if not output_path:
            QMessageBox.warning(self, "警告", "请选择有效的输出文件")
            return
        
        key_id = self.file_key_select.currentData()
        if not key_id:
            QMessageBox.warning(self, "警告", "请选择密钥")
            return
        
        try:
            # 获取密钥
            key = self.key_manager.get_key(key_id=key_id)
            if not key:
                raise ValueError("获取密钥失败")
            
            # 创建并启动解密线程
            self.file_decryption_thread = EncryptionThread(
                func=lambda input_path, output_path, key: self.crypto_engine.decrypt_file(input_path, output_path, key),
                args=(input_path, output_path, key),
                kwargs={}
            )
            
            self.file_decryption_thread.progress_update.connect(self.file_progress.setValue)
            self.file_decryption_thread.finished.connect(self.handle_file_decryption_result)
            self.file_decryption_thread.error.connect(self.handle_file_operation_error)
            
            self.file_decryption_thread.start()
            
            # 禁用按钮直到解密完成
            self.encrypt_file_btn.setEnabled(False)
            self.decrypt_file_btn.setEnabled(False)
            
        except Exception as e:
            QMessageBox.critical(self, "文件解密错误", str(e))
    
    def handle_file_decryption_result(self, result):
        """处理文件解密结果"""
        try:
            # 修复这里，处理result可能是字典的情况
            if isinstance(result, dict) and 'result' in result:
                decryption_time = result['result']
            else:
                decryption_time = result
            
            # 显示结果
            file_size = os.path.getsize(self.file_input_path.text()) / (1024 * 1024)  # MB
            
            # 避免除零错误，确保解密时间至少为1毫秒
            decryption_time_sec = max(decryption_time / 1000, 0.001)  # 转换为秒并确保不为零
            throughput = file_size / decryption_time_sec
            
            self.file_result_text.setText(
                f"文件解密成功！\n"
                f"输出文件: {self.file_output_path.text()}\n"
                f"文件大小: {file_size:.2f} MB\n"
                f"解密时间: {decryption_time:.2f} ms\n"
                f"解密吞吐量: {throughput:.2f} MB/s"
            )
            
            # 恢复按钮状态
            self.encrypt_file_btn.setEnabled(True)
            self.decrypt_file_btn.setEnabled(True)
            
            self.statusBar().showMessage("文件解密完成")
            
        except Exception as e:
            print(f"处理文件解密结果错误: {str(e)}")
            QMessageBox.critical(self, "处理文件解密结果错误", str(e))
            self.encrypt_file_btn.setEnabled(True)
            self.decrypt_file_btn.setEnabled(True)
    
    def handle_file_operation_error(self, error_msg):
        """处理文件操作错误"""
        QMessageBox.critical(self, "文件操作错误", error_msg)
        self.encrypt_file_btn.setEnabled(True)
        self.decrypt_file_btn.setEnabled(True)
        self.file_progress.setValue(0)
    
    def generate_new_key(self):
        """生成新密钥并添加到下拉框"""
        key_name, ok = QInputDialog.getText(self, "新密钥", "输入密钥名称:")
        if ok and key_name:
            try:
                key_id, gen_time = self.key_manager.create_key(key_name)
                QMessageBox.information(self, "密钥生成成功", 
                                       f"密钥创建成功！\nID: {key_id}\n生成时间: {gen_time:.2f}ms")
                
                # 刷新所有密钥下拉框
                self.refresh_key_combobox(self.text_key_select)
                self.refresh_key_combobox(self.file_key_select)
                self.refresh_key_combobox(self.image_key_select)
                self.refresh_key_combobox(self.security_key_select)
                self.refresh_key_combobox(self.perf_key_select)
                
                # 选择新创建的密钥
                index = self.text_key_select.findData(key_id)
                if index >= 0:
                    self.text_key_select.setCurrentIndex(index)
            except Exception as e:
                QMessageBox.critical(self, "错误", f"创建密钥失败: {str(e)}")
    
    def performance_test(self):
        """执行性能测试"""
        # 简单性能测试示例
        try:
            key_id = self.perf_key_select.currentData()
            if not key_id:
                QMessageBox.warning(self, "警告", "请先选择一个密钥")
                return
            
            # 获取测试输入
            test_input = self.perf_test_input.toPlainText()
            if not test_input:
                QMessageBox.warning(self, "警告", "请输入测试文本")
                return
            
            # 运行性能分析器
            iterations = self.perf_iterations.value()
            results = self.performance_analyzer.analyze_text_operations(
                test_input, 
                key_id=key_id,
                iterations=iterations,
                key_manager=self.key_manager,
                crypto_engine=self.crypto_engine
            )
            
            # 更新结果显示
            self.update_performance_results(results)
            
        except Exception as e:
            QMessageBox.critical(self, "错误", f"性能测试失败: {str(e)}")

    def browse_input_image(self):
        """浏览输入图像"""
        fname, _ = QFileDialog.getOpenFileName(self, "选择输入图像", "", "图像文件 (*.png *.jpg *.jpeg *.bmp *.gif)")
        if fname:
            self.image_input_path.setText(fname)
            
            # 加载并显示原始图像
            pixmap = QPixmap(fname)
            if not pixmap.isNull():
                pixmap = pixmap.scaled(300, 300, Qt.KeepAspectRatio)
                self.original_image_label.setPixmap(pixmap)
            
            # 自动设置输出图像路径
            base, ext = os.path.splitext(fname)
            if self.image_algorithm.currentData() == "chaotic":
                self.image_output_path.setText(f"{base}_chaotic{ext}")
            else:
                self.image_output_path.setText(f"{base}_encrypted{ext}")
    
    def browse_output_image(self):
        """浏览输出图像"""
        fname, _ = QFileDialog.getSaveFileName(self, "选择输出图像", "", "图像文件 (*.png *.jpg *.jpeg *.bmp)")
        if fname:
            self.image_output_path.setText(fname)
    
    def encrypt_image(self):
        """加密图像"""
        input_path = self.image_input_path.text()
        output_path = self.image_output_path.text()
        
        if not input_path or not os.path.exists(input_path):
            QMessageBox.warning(self, "警告", "请选择有效的输入图像")
            return
            
        if not output_path:
            QMessageBox.warning(self, "警告", "请选择有效的输出图像")
            return
        
        key_id = self.image_key_select.currentData()
        if not key_id:
            QMessageBox.warning(self, "警告", "请选择密钥")
            return
        
        try:
            # 获取密钥
            key = self.key_manager.get_key(key_id=key_id)
            if not key:
                raise ValueError("获取密钥失败")
            
            # 根据选择的算法决定使用哪个加密函数
            if self.image_algorithm.currentData() == "chaotic":
                encrypt_func = self.image_crypto.encrypt_image_chaotic
            else:
                encrypt_func = self.image_crypto.encrypt_image
            
            # 创建并启动加密线程
            self.image_encryption_thread = EncryptionThread(
                func=encrypt_func,
                args=(input_path, key, output_path),
                kwargs={}
            )
            
            self.image_encryption_thread.progress_update.connect(self.image_progress.setValue)
            self.image_encryption_thread.finished.connect(self.handle_image_encryption_result)
            self.image_encryption_thread.error.connect(self.handle_image_operation_error)
            
            self.image_encryption_thread.start()
            
            # 禁用按钮直到加密完成
            self.encrypt_image_btn.setEnabled(False)
            self.decrypt_image_btn.setEnabled(False)
            
        except Exception as e:
            QMessageBox.critical(self, "图像加密错误", str(e))
    
    def handle_image_encryption_result(self, result):
        """处理图像加密结果"""
        try:
            # 处理result可能是嵌套字典的情况
            if isinstance(result, dict) and 'result' in result and isinstance(result['result'], dict):
                # 如果result['result']是一个字典，说明原始返回值已经是字典
                result = result['result']
            
            # 显示结果
            output_path = result.get('output_path')
            
            # 更新结果图像显示
            if output_path and os.path.exists(output_path):
                # 添加调试信息
                print(f"正在加载加密后的图像: {output_path}")
                self.statusBar().showMessage(f"正在加载加密后的图像: {output_path}")
                
                # 区分不同加密算法的显示逻辑
                if self.image_algorithm.currentData() == "chaotic":
                    # 混沌加密保存为标准图像文件，可以直接显示
                    try:
                        pixmap = QPixmap(output_path)
                        if not pixmap.isNull():
                            pixmap = pixmap.scaled(300, 300, Qt.KeepAspectRatio, Qt.SmoothTransformation)
                            self.encrypted_image_label.setPixmap(pixmap)
                            self.encrypted_image_label.setScaledContents(False)
                        else:
                            print(f"无法加载混沌加密图像: {output_path}")
                            self.encrypted_image_label.setText("无法加载加密后的图像")
                    except Exception as img_error:
                        print(f"加载混沌加密图像时出错: {str(img_error)}")
                        self.encrypted_image_label.setText(f"图像加载错误: {str(img_error)}")
                else:
                    # AES加密保存为二进制文件，需要创建临时图像显示
                    try:
                        # 设置一个提示信息
                        self.encrypted_image_label.setText("已加密(二进制数据)")
                        
                        # 创建一个临时图像表示加密状态
                        temp_image = Image.new('RGB', (300, 300), color=(100, 100, 100))
                        temp_byte_arr = io.BytesIO()
                        temp_image.save(temp_byte_arr, format='PNG')
                        temp_bytes = temp_byte_arr.getvalue()
                        
                        # 显示临时图像
                        pixmap = QPixmap()
                        pixmap.loadFromData(temp_bytes)
                        if not pixmap.isNull():
                            self.encrypted_image_label.setPixmap(pixmap)
                    except Exception as img_error:
                        print(f"创建加密图像表示时出错: {str(img_error)}")
                        self.encrypted_image_label.setText(f"图像加载错误: {str(img_error)}")
            else:
                # 输出路径不存在
                print(f"加密后的图像路径无效: {output_path}")
                self.encrypted_image_label.setText("加密后的图像路径无效")
            
            # 显示性能信息
            execution_time = result.get('execution_time_ms', 0)
            data_size = result.get('data_size_mb', 0)
            performance = result.get('performance_mbps', 0)
            
            self.image_result_text.setText(
                f"图像加密成功！\n"
                f"输出图像: {output_path}\n"
                f"图像大小: {data_size:.2f} MB\n"
                f"加密时间: {execution_time:.2f} ms\n"
                f"加密吞吐量: {performance:.2f} MB/s"
            )
            
            # 恢复按钮状态
            self.encrypt_image_btn.setEnabled(True)
            self.decrypt_image_btn.setEnabled(True)
            
            self.statusBar().showMessage("图像加密完成")
            
        except Exception as e:
            print(f"处理图像加密结果错误: {str(e)}")
            QMessageBox.critical(self, "处理图像加密结果错误", str(e))
            self.encrypt_image_btn.setEnabled(True)
            self.decrypt_image_btn.setEnabled(True)
    
    def decrypt_image(self):
        """解密图像"""
        input_path = self.image_input_path.text()
        output_path = self.image_output_path.text()
        
        if not input_path or not os.path.exists(input_path):
            QMessageBox.warning(self, "警告", "请选择有效的输入图像")
            return
            
        if not output_path:
            QMessageBox.warning(self, "警告", "请选择有效的输出图像")
            return
        
        key_id = self.image_key_select.currentData()
        if not key_id:
            QMessageBox.warning(self, "警告", "请选择密钥")
            return
        
        try:
            # 获取密钥
            key = self.key_manager.get_key(key_id=key_id)
            if not key:
                raise ValueError("获取密钥失败")
            
            # 根据选择的算法决定使用哪个解密函数
            if self.image_algorithm.currentData() == "chaotic":
                # 对于混沌算法，需要元数据文件
                metadata_path = f"{os.path.splitext(input_path)[0]}.meta"
                if not os.path.exists(metadata_path):
                    raise ValueError("未找到图像元数据文件，无法解密")
                
                decrypt_func = lambda input_path, key, output_path: self.image_crypto.decrypt_image_chaotic(
                    input_path, key, metadata_path, output_path
                )
            else:
                decrypt_func = self.image_crypto.decrypt_image
            
            # 创建并启动解密线程
            self.image_decryption_thread = EncryptionThread(
                func=decrypt_func,
                args=(input_path, key, output_path),
                kwargs={}
            )
            
            self.image_decryption_thread.progress_update.connect(self.image_progress.setValue)
            self.image_decryption_thread.finished.connect(self.handle_image_decryption_result)
            self.image_decryption_thread.error.connect(self.handle_image_operation_error)
            
            self.image_decryption_thread.start()
            
            # 禁用按钮直到解密完成
            self.encrypt_image_btn.setEnabled(False)
            self.decrypt_image_btn.setEnabled(False)
            
        except Exception as e:
            QMessageBox.critical(self, "图像解密错误", str(e))
    
    def handle_image_decryption_result(self, result):
        """处理图像解密结果"""
        try:
            # 处理result可能是嵌套字典的情况
            if isinstance(result, dict) and 'result' in result and isinstance(result['result'], dict):
                # 如果result['result']是一个字典，说明原始返回值已经是字典
                result = result['result']
            
            # 显示结果
            output_path = result.get('output_path')
            
            # 更新结果图像显示
            if output_path and os.path.exists(output_path):
                # 添加调试信息
                print(f"正在加载解密后的图像: {output_path}")
                self.statusBar().showMessage(f"正在加载解密后的图像: {output_path}")
                
                # 解密后的结果应该是标准图像文件，直接显示
                try:
                    pixmap = QPixmap(output_path)
                    if not pixmap.isNull():
                        pixmap = pixmap.scaled(300, 300, Qt.KeepAspectRatio, Qt.SmoothTransformation)
                        self.encrypted_image_label.setPixmap(pixmap)
                        self.encrypted_image_label.setScaledContents(False)
                    else:
                        print(f"无法加载解密后的图像: {output_path}")
                        self.encrypted_image_label.setText("无法加载解密后的图像")
                except Exception as img_error:
                    print(f"加载解密后的图像时出错: {str(img_error)}")
                    self.encrypted_image_label.setText(f"图像加载错误: {str(img_error)}")
            else:
                # 输出路径不存在
                print(f"解密后的图像路径无效: {output_path}")
                self.encrypted_image_label.setText("解密后的图像路径无效")
            
            # 显示性能信息
            execution_time = result.get('execution_time_ms', 0)
            data_size = result.get('data_size_mb', 0)
            performance = result.get('performance_mbps', 0)
            
            self.image_result_text.setText(
                f"图像解密成功！\n"
                f"输出图像: {output_path}\n"
                f"图像大小: {data_size:.2f} MB\n"
                f"解密时间: {execution_time:.2f} ms\n"
                f"解密吞吐量: {performance:.2f} MB/s"
            )
            
            # 恢复按钮状态
            self.encrypt_image_btn.setEnabled(True)
            self.decrypt_image_btn.setEnabled(True)
            
            self.statusBar().showMessage("图像解密完成")
            
        except Exception as e:
            print(f"处理图像解密结果错误: {str(e)}")
            QMessageBox.critical(self, "处理图像解密结果错误", str(e))
            self.encrypt_image_btn.setEnabled(True)
            self.decrypt_image_btn.setEnabled(True)
    
    def handle_image_operation_error(self, error_msg):
        """处理图像操作错误"""
        QMessageBox.critical(self, "图像操作错误", error_msg)
        self.encrypt_image_btn.setEnabled(True)
        self.decrypt_image_btn.setEnabled(True)
        self.image_progress.setValue(0)

    def update_performance_results(self, results):
        """更新性能测试结果显示"""
        # 清除之前的结果
        self.perf_results.clear()
        
        # 显示文本形式的结果摘要
        summary = f"性能测试结果摘要:\n\n"
        summary += f"加密操作:\n"
        summary += f"  平均执行时间: {results['encryption']['avg_time']:.2f} ms\n"
        summary += f"  最小执行时间: {results['encryption']['min_time']:.2f} ms\n"
        summary += f"  最大执行时间: {results['encryption']['max_time']:.2f} ms\n"
        summary += f"  标准差: {results['encryption']['std_dev']:.2f} ms\n\n"
        
        summary += f"解密操作:\n"
        summary += f"  平均执行时间: {results['decryption']['avg_time']:.2f} ms\n"
        summary += f"  最小执行时间: {results['decryption']['min_time']:.2f} ms\n"
        summary += f"  最大执行时间: {results['decryption']['max_time']:.2f} ms\n"
        summary += f"  标准差: {results['decryption']['std_dev']:.2f} ms\n\n"
        
        summary += f"密钥检索操作:\n"
        summary += f"  平均执行时间: {results['key_retrieval']['avg_time']:.2f} ms\n"
        
        summary += f"\nCPU使用率: {results['system']['cpu_percent']:.1f}%\n"
        summary += f"内存使用: {results['system']['memory_used']:.2f} MB\n"
        
        self.perf_results.setText(summary)
        
        # 更新图表，如果存在的话
        try:
            # 尝试使用perf_viz_canvas属性
            canvas = self.perf_viz_canvas
            canvas.axes.clear()
            
            # 绘制柱状图
            labels = ['加密', '解密', '密钥检索']
            times = [
                results['encryption']['avg_time'], 
                results['decryption']['avg_time'],
                results['key_retrieval']['avg_time']
            ]
            
            x = range(len(labels))
            canvas.axes.bar(x, times, align='center', alpha=0.7)
            canvas.axes.set_xticks(x)
            canvas.axes.set_xticklabels(labels)
            canvas.axes.set_ylabel('执行时间 (ms)')
            canvas.axes.set_title('各操作平均执行时间')
            
            # 刷新图表
            canvas.draw()
        except AttributeError:
            # 如果图表组件不存在或命名不同，则忽略图表更新
            pass

def main():
    """主函数，启动GUI应用"""
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
    
if __name__ == "__main__":
    main() 